کلاسهای تودر تو و داخلی در کاتلین
درین نصیب از نوشتهیعلمی آمورش کاتلین به تحقیق کلاسهای داخل هم و داخلی به یاری نمونههای طراحی اپلیکیشن در مشهد متفاوت می پردازیم.
کلاس تودر تو در کاتلین
کاتلین همچون جاوا قابلیت و امکان تعریف و تمجید یک کلاس باطن کلاس دیگر را به طور کلاس تو درتو مهیا ساخته میباشد.
1class Outer {
2 ... .. ...
3 class Nested {
4 ... .. ...
5 }
6}
از آنجا که کلاس nested یک عضو از کلاس بیرونی خویش به اسم Outer میباشد، می توانید با استعمال از نشان نقطه (.) به کلاس Nested و اعضای آن دسترسی داشته باشید.
مثالی از کلاس تودرتوی کاتلین
1class Outer {
2
3 val a = "Outside Nested class."
4
5 class Nested {
6 val b = "Inside Nested class."
7 fun callMe() = "Function call from inside Nested class."
8 }
9}
10
11fun main(args: Array) {
12 // accessing member of Nested class
13 println(Outer.Nested().b)
14
15 // creating object of Nested class
16 val nested = Outer.Nested()
17 println(nested.callMe())
18}
مشاهده بدون نقص کدها
خروجی نرمافزار فوق به طور پایین میباشد:
Inside Nested class.
Function call from inside Nested class.
دقت فرمایید که کلاس تودر تو در کاتلین شبیه کلاس تودرتوی استاتیک در جاوا میباشد. در گویش جاوا وقتی که یک کلاس را باطن کلاس دیگری اعلان میکنید، به طور پیشفرض به طور یک کلاس درونی درمیآید. با این حالا در کاتلین می بایست از مادیفایر inner برای ساخت و ساز کلاس درونی استعمال فرمایید. دراین خصوص در پی بیشتر توضیح خوا هیم بخشید.
کلاسهای درونی در کاتلین
کلاسهای تودرتوی در کاتلین به نوبت کلاس بیرونی دسترسی ندارند. به نمونه ذیل دقت نمایید:
1class Outer {
2 val foo = "Outside Nested class."
3
4 class Nested {
5 // Error! cannot access member of outer class.
6 fun callMe() = foo
7 }
8}
9
10fun main(args: Array) {
11
12 val outer = Outer()
13 println(outer.Nested().callMe())
14}
کد فوق کامپایل نمیشود، چون کوشش کردیم که به مشخصه foo کلاس Outer از باطن کلاس Nested دسترسی پیدا کنیم.
برای حل این نقص، بایستی کلاس داخل هم را با کلیدواژه inner نشانگذاری نمایید تا یک کلاس درونی ساختوساز خواهد شد. کلاسهای درونی یک ارجاع به کلاس بیرونی داراهستند و میتوانند به اعضای کلاس بیرونی دسترسی داشته باشند.
مثالی از کلاس درونی در کاتلین
1class Outer {
2
3 val a = "Outside Nested class."
4
5 inner class Inner {
6 fun callMe() = a
7 }
8}
9
10fun main(args: Array) {
11
12 val outer = Outer()
13 println("Using outer object: ${outer.Inner().callMe()}")
14
15 val inner = Outer().Inner()
16 println("Using inner object: ${inner.callMe()}")
17}
مشاهده بدون نقص کدها
خروجی اپ فوق به طور تحت میباشد:
Using outer object: Outside Nested class.
Using inner object: Outside Nested class.
کلاس داده در کاتلین
دراین قسمت از نوشتهیعلمی فراگیری کاتلین با طریق ساخت و ساز کلاسهای داده در کاتلین آشنا خواهیم شد. همینطور به رسیدگی الزاماتی که کلاس داده بایستی داشته باشد و کارکردهای استاندارد آن میپردازیم.
در پارهای موردها مورد نیاز میباشد که یک کلاس فقطً برای محافظت دادهها ساخت و ساز گردد. در یک اینگونه حالتهایی بایستی کلاس را به طور data نمادگذاری کنیم تا یک کلاس داده ساخت و ساز خواهد شد. به نمونه پایین دقت نمائید.
data class Person(val name: String, var age: Int)
کامپایلر در خصوص این کلاس، مفاد ذیل را به طور اتومات ساخت مینماید:
تابع ()copy، جفت ()equals و ()hashCode و ()toString از تولید کننده نخستین ساخت میشوند.
تابعهای ()componentN نیز ساخته میشوند.
قبل از آن که به پژوهش تفصیلی این امکانها بپردازیم، می بایست در خصوص الزاماتی که کلاس داده بایستی داشته باشد حرف کنیم.
ملزومات کلاس داده در کاتلین
الزاماتی که کلاس داده بایستی برآورده سازد به تفصیل تحت میباشند:
تولیدکننده اول بایستی دستکم یک پارامتر داشته باشد.
پارامترهای تولید کننده نخستین بایستی به طور val (فقط-خواندنی) یا این که var (تلاوت-تایپ کردن) آرمگذاری شوند.
کلاس نمیتواند به طور open ،abstract ،inner و یا این که sealed باشد.
کلاس میتواند کلاسهای دیگر را گسترش دهد یا این که اینترفیسها را پیادهسازی نماید. در شرایطیکه از ورژن 1.1 کاتلین به کار گیری میکنید،، کلاس قادر است صرفا اینترفیسها را پیادهسازی نماید.
مثالی از کلاس داده در کاتلین
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val jack = User("jack", 29)
5 println("name = ${jack.name}")
6 println("age = ${jack.age}")
7}
خروجی اپلیکیشن فوق به طور تحت میباشد:
name = jack
age = 29
وقتی که یک کلاس داده را اعلان می کنیم، کامپایلر به طور اتوماتیک یک سری تابع مانند ()toString() ،equals() ،hashcode و غیره را در پسقضیه ساخت و ساز مینماید. این عمل به مراقبت انسجام کد امداد مینماید. درصورتیکه با جاوا عمل کرده باشید، می دانید که برای اجرای این کارکردها مقدار متعددی کد قالبی بنویسید. بهدنبال با نحوه به کار گیری از این تابعها آشنا میشویم:
Copying
در ارتباط یک کلاس داده، می توانیم یک نسخه برداری از یک شیء را با تغییرو تحول در بعضی از مشخصههای آن با به کارگیری تابع ()copy ساخت و ساز کنیم. شیوه فعالیت آن به طور ذیل میباشد:
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val u1 = User("John", 29)
5
6 // using copy function to create an object
7 val u2 = u1.copy(name = "Randy")
8
9 println("u1: name = ${u1.name}, name = ${u1.age}")
10 println("u2: name = ${u2.name}, name = ${u2.age}")
11}
خروجی نرم افزار فوق به طور تحت میباشد:
u1: name = John, name = 29
u2: name = Randy, name = 29
تابع ()toString یک بازنمایی حرفهای از یک شیء رجوع میدهد:
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val u1 = User("John", 29)
5 println(u1.toString())
6}
خروجی نرمافزار فوق به طور ذیل میباشد:
User(name=John, age=29)
()hashCode و ()equals
روال ()hasCode کد هش یک شیء را رجوع میدهد. در شرایطیکه دو شیء موازی باشند، ()hashCode فیض درست یکسانی را ایجاد مینماید. درحالتی که که دو شیء موازی باشند، اسلوب ()equals مقدار true رجوع می دهد. در صورتی اشیاء موازی نباشند، روال ()equals مقدار false برگشت می دهد.
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val u1 = User("John", 29)
5 val u2 = u1.copy()
6 val u3 = u1.copy(name = "Amanda")
7
8 println("u1 hashcode = ${u1.hashCode()}")
9 println("u2 hashcode = ${u2.hashCode()}")
10 println("u3 hashcode = ${u3.hashCode()}")
11
12 if (u1.equals(u2) == true)
13 println("u1 is equal to u2.")
14 else
15 println("u1 is not equal to u2.")
16
17 if (u1.equals(u3) == true)
18 println("u1 is equal to u3.")
19 else
20 println("u1 is not equal to u3.")
21}
مشاهده بی نقص کدها
خروجی اپلیکیشن فوق به طور ذیل میباشد:
u1 hashcode = 71750738
u2 hashcode = 71750738
u3 hashcode = 771732263
u1 is equal to u2.
u1 is not equal to u3.
تخریب اعلانها
قابلیت تخریب یک شیء با شکل چندین متغیر با به کار گیری از اعلانهای destructing وجود داراست. به نمونه ذیل اعتنا نمایید:
1data class User(val name: String, val age: Int, val gender: String)
2
3fun main(args: Array) {
4 val u1 = User("John", 29, "Male")
5
6 val (name, age, gender) = u1
7 println("name = $name")
8 println("age = $age")
9 println("gender = $gender")
10}
خروجی نرم افزار فوق به طور ذیل میباشد:
name = John
age = 29
gender = Male
این طرز بدین عامل ممکن میباشد که کامپایلر تمامی مشخصههای تابعهای ()componentN را برای کلاس داده ایجاد مینماید. به نمونه تحت اعتنا نمایید:
1data class User(val name: String, val age: Int, val gender: String)
2
3fun main(args: Array) {
4 val u1 = User("John", 29, "Male")
5
6 println(u1.component1()) // John
7 println(u1.component2()) // 29
8 println(u1.component3()) // "Male"
9}
خروجی اپ فوق به طور زیراست:
John
29
Male
کلاسهای Sealed در کاتلین
دراین قسمت از نوشته ی علمی فراگیری کاتلین دربارهی کلاسهای Sealed، روش ساخت و مجال استعمال از آنهارا به همدم نمونه تحقیق می کنیم.
کلاسهای Sealed وقتی به کار گیری می گردند که صرفا یکیاز اشکال از دربین گروه محصور را داشته باشد. قبل از تحقیق ریزه کاری کلاسهای Sealed آغاز به رسیدگی مسائلی که آنان حل مینمایند، میپردازیم. به نمونه تحت اعتنا نمایید:
1class Expr
2class Const(val value: Int) : Expr
3class Sum(val left: Expr, val right: Expr) : Expr
4
5fun eval(e: Expr): Int =
6 when (e) {
7 is Const -> e.value
8 is Sum -> eval(e.right) + eval(e.left)
9 else ->
10 throw IllegalArgumentException("Unknown expression")
11 }
در اپ فوق، کلاس مبنای Expr کلاس مشتقگردیده به اسمهای Const (اکران یکی) و sum (اکران تمام دو عبارت) دارااست. دراین حالت به کار گیری از شاخه else برای شرط پیشفرض در عبارت when ضروری میباشد.
اینک درحالتی که یک زیرکلاس از کلاس Expr داشته باشیم، کامپایلر هیچ چیزی را تشخیص نمیدهد، چون شاخه else آن را رئیس مینماید که می تواند سبب به بروز باگ گردد. با این هم اکنون، در صورتیکه که کامپایلر در طی اضافه کردن یک زیرکلاس تازه خطایی ساخت و ساز نماید، عالی خواهد بود.
برای حل این زمینه، می توانید از کلاسهای sealed به کارگیری فرمایید. چنان که اشاره کردیم، کلاس sealed قابلیت و امکان ساخت و ساز زیرکلاس را محصور میسازد. همینطور هنگامی که تمامی زیرکلاسهای یک کلاس sealed به طور یک عبارت when باشند، لزومی به به کارگیری از شاخه else نخواهد بود.
برای ساختوساز یک کلاس sealed، بایستی از مادیفایر sealed مانند نمونه پایین به کارگیری فرمایید:
sealed class Expr
کلاسهای تودر تو و داخلی در کاتلین
درین نصیب از نوشتهیعلمی آمورش کاتلین به تحقیق کلاسهای داخل هم و داخلی به یاری نمونههای طراحی اپلیکیشن در مشهد متفاوت می پردازیم.
کلاس تودر تو در کاتلین
کاتلین همچون جاوا قابلیت و امکان تعریف و تمجید یک کلاس باطن کلاس دیگر را به طور کلاس تو درتو مهیا ساخته میباشد.
1class Outer {
2 ... .. ...
3 class Nested {
4 ... .. ...
5 }
6}
از آنجا که کلاس nested یک عضو از کلاس بیرونی خویش به اسم Outer میباشد، می توانید با استعمال از نشان نقطه (.) به کلاس Nested و اعضای آن دسترسی داشته باشید.
مثالی از کلاس تودرتوی کاتلین
1class Outer {
2
3 val a = "Outside Nested class."
4
5 class Nested {
6 val b = "Inside Nested class."
7 fun callMe() = "Function call from inside Nested class."
8 }
9}
10
11fun main(args: Array) {
12 // accessing member of Nested class
13 println(Outer.Nested().b)
14
15 // creating object of Nested class
16 val nested = Outer.Nested()
17 println(nested.callMe())
18}
مشاهده بدون نقص کدها
خروجی نرمافزار فوق به طور پایین میباشد:
Inside Nested class.
Function call from inside Nested class.
دقت فرمایید که کلاس تودر تو در کاتلین شبیه کلاس تودرتوی استاتیک در جاوا میباشد. در گویش جاوا وقتی که یک کلاس را باطن کلاس دیگری اعلان میکنید، به طور پیشفرض به طور یک کلاس درونی درمیآید. با این حالا در کاتلین می بایست از مادیفایر inner برای ساخت و ساز کلاس درونی استعمال فرمایید. دراین خصوص در پی بیشتر توضیح خوا هیم بخشید.
کلاسهای درونی در کاتلین
کلاسهای تودرتوی در کاتلین به نوبت کلاس بیرونی دسترسی ندارند. به نمونه ذیل دقت نمایید:
1class Outer {
2 val foo = "Outside Nested class."
3
4 class Nested {
5 // Error! cannot access member of outer class.
6 fun callMe() = foo
7 }
8}
9
10fun main(args: Array) {
11
12 val outer = Outer()
13 println(outer.Nested().callMe())
14}
کد فوق کامپایل نمیشود، چون کوشش کردیم که به مشخصه foo کلاس Outer از باطن کلاس Nested دسترسی پیدا کنیم.
برای حل این نقص، بایستی کلاس داخل هم را با کلیدواژه inner نشانگذاری نمایید تا یک کلاس درونی ساختوساز خواهد شد. کلاسهای درونی یک ارجاع به کلاس بیرونی داراهستند و میتوانند به اعضای کلاس بیرونی دسترسی داشته باشند.
مثالی از کلاس درونی در کاتلین
1class Outer {
2
3 val a = "Outside Nested class."
4
5 inner class Inner {
6 fun callMe() = a
7 }
8}
9
10fun main(args: Array) {
11
12 val outer = Outer()
13 println("Using outer object: ${outer.Inner().callMe()}")
14
15 val inner = Outer().Inner()
16 println("Using inner object: ${inner.callMe()}")
17}
مشاهده بدون نقص کدها
خروجی اپ فوق به طور تحت میباشد:
Using outer object: Outside Nested class.
Using inner object: Outside Nested class.
کلاس داده در کاتلین
دراین قسمت از نوشتهیعلمی فراگیری کاتلین با طریق ساخت و ساز کلاسهای داده در کاتلین آشنا خواهیم شد. همینطور به رسیدگی الزاماتی که کلاس داده بایستی داشته باشد و کارکردهای استاندارد آن میپردازیم.
در پارهای موردها مورد نیاز میباشد که یک کلاس فقطً برای محافظت دادهها ساخت و ساز گردد. در یک اینگونه حالتهایی بایستی کلاس را به طور data نمادگذاری کنیم تا یک کلاس داده ساخت و ساز خواهد شد. به نمونه پایین دقت نمائید.
data class Person(val name: String, var age: Int)
کامپایلر در خصوص این کلاس، مفاد ذیل را به طور اتومات ساخت مینماید:
تابع ()copy، جفت ()equals و ()hashCode و ()toString از تولید کننده نخستین ساخت میشوند.
تابعهای ()componentN نیز ساخته میشوند.
قبل از آن که به پژوهش تفصیلی این امکانها بپردازیم، می بایست در خصوص الزاماتی که کلاس داده بایستی داشته باشد حرف کنیم.
ملزومات کلاس داده در کاتلین
الزاماتی که کلاس داده بایستی برآورده سازد به تفصیل تحت میباشند:
تولیدکننده اول بایستی دستکم یک پارامتر داشته باشد.
پارامترهای تولید کننده نخستین بایستی به طور val (فقط-خواندنی) یا این که var (تلاوت-تایپ کردن) آرمگذاری شوند.
کلاس نمیتواند به طور open ،abstract ،inner و یا این که sealed باشد.
کلاس میتواند کلاسهای دیگر را گسترش دهد یا این که اینترفیسها را پیادهسازی نماید. در شرایطیکه از ورژن 1.1 کاتلین به کار گیری میکنید،، کلاس قادر است صرفا اینترفیسها را پیادهسازی نماید.
مثالی از کلاس داده در کاتلین
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val jack = User("jack", 29)
5 println("name = ${jack.name}")
6 println("age = ${jack.age}")
7}
خروجی اپلیکیشن فوق به طور تحت میباشد:
name = jack
age = 29
وقتی که یک کلاس داده را اعلان می کنیم، کامپایلر به طور اتوماتیک یک سری تابع مانند ()toString() ،equals() ،hashcode و غیره را در پسقضیه ساخت و ساز مینماید. این عمل به مراقبت انسجام کد امداد مینماید. درصورتیکه با جاوا عمل کرده باشید، می دانید که برای اجرای این کارکردها مقدار متعددی کد قالبی بنویسید. بهدنبال با نحوه به کار گیری از این تابعها آشنا میشویم:
Copying
در ارتباط یک کلاس داده، می توانیم یک نسخه برداری از یک شیء را با تغییرو تحول در بعضی از مشخصههای آن با به کارگیری تابع ()copy ساخت و ساز کنیم. شیوه فعالیت آن به طور ذیل میباشد:
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val u1 = User("John", 29)
5
6 // using copy function to create an object
7 val u2 = u1.copy(name = "Randy")
8
9 println("u1: name = ${u1.name}, name = ${u1.age}")
10 println("u2: name = ${u2.name}, name = ${u2.age}")
11}
خروجی نرم افزار فوق به طور تحت میباشد:
u1: name = John, name = 29
u2: name = Randy, name = 29
تابع ()toString یک بازنمایی حرفهای از یک شیء رجوع میدهد:
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val u1 = User("John", 29)
5 println(u1.toString())
6}
خروجی نرمافزار فوق به طور ذیل میباشد:
User(name=John, age=29)
()hashCode و ()equals
روال ()hasCode کد هش یک شیء را رجوع میدهد. در شرایطیکه دو شیء موازی باشند، ()hashCode فیض درست یکسانی را ایجاد مینماید. درحالتی که که دو شیء موازی باشند، اسلوب ()equals مقدار true رجوع می دهد. در صورتی اشیاء موازی نباشند، روال ()equals مقدار false برگشت می دهد.
1data class User(val name: String, val age: Int)
2
3fun main(args: Array) {
4 val u1 = User("John", 29)
5 val u2 = u1.copy()
6 val u3 = u1.copy(name = "Amanda")
7
8 println("u1 hashcode = ${u1.hashCode()}")
9 println("u2 hashcode = ${u2.hashCode()}")
10 println("u3 hashcode = ${u3.hashCode()}")
11
12 if (u1.equals(u2) == true)
13 println("u1 is equal to u2.")
14 else
15 println("u1 is not equal to u2.")
16
17 if (u1.equals(u3) == true)
18 println("u1 is equal to u3.")
19 else
20 println("u1 is not equal to u3.")
21}
مشاهده بی نقص کدها
خروجی اپلیکیشن فوق به طور ذیل میباشد:
u1 hashcode = 71750738
u2 hashcode = 71750738
u3 hashcode = 771732263
u1 is equal to u2.
u1 is not equal to u3.
تخریب اعلانها
قابلیت تخریب یک شیء با شکل چندین متغیر با به کار گیری از اعلانهای destructing وجود داراست. به نمونه ذیل اعتنا نمایید:
1data class User(val name: String, val age: Int, val gender: String)
2
3fun main(args: Array) {
4 val u1 = User("John", 29, "Male")
5
6 val (name, age, gender) = u1
7 println("name = $name")
8 println("age = $age")
9 println("gender = $gender")
10}
خروجی نرم افزار فوق به طور ذیل میباشد:
name = John
age = 29
gender = Male
این طرز بدین عامل ممکن میباشد که کامپایلر تمامی مشخصههای تابعهای ()componentN را برای کلاس داده ایجاد مینماید. به نمونه تحت اعتنا نمایید:
1data class User(val name: String, val age: Int, val gender: String)
2
3fun main(args: Array) {
4 val u1 = User("John", 29, "Male")
5
6 println(u1.component1()) // John
7 println(u1.component2()) // 29
8 println(u1.component3()) // "Male"
9}
خروجی اپ فوق به طور زیراست:
John
29
Male
کلاسهای Sealed در کاتلین
دراین قسمت از نوشته ی علمی فراگیری کاتلین دربارهی کلاسهای Sealed، روش ساخت و مجال استعمال از آنهارا به همدم نمونه تحقیق می کنیم.
کلاسهای Sealed وقتی به کار گیری می گردند که صرفا یکیاز اشکال از دربین گروه محصور را داشته باشد. قبل از تحقیق ریزه کاری کلاسهای Sealed آغاز به رسیدگی مسائلی که آنان حل مینمایند، میپردازیم. به نمونه تحت اعتنا نمایید:
1class Expr
2class Const(val value: Int) : Expr
3class Sum(val left: Expr, val right: Expr) : Expr
4
5fun eval(e: Expr): Int =
6 when (e) {
7 is Const -> e.value
8 is Sum -> eval(e.right) + eval(e.left)
9 else ->
10 throw IllegalArgumentException("Unknown expression")
11 }
در اپ فوق، کلاس مبنای Expr کلاس مشتقگردیده به اسمهای Const (اکران یکی) و sum (اکران تمام دو عبارت) دارااست. دراین حالت به کار گیری از شاخه else برای شرط پیشفرض در عبارت when ضروری میباشد.
اینک درحالتی که یک زیرکلاس از کلاس Expr داشته باشیم، کامپایلر هیچ چیزی را تشخیص نمیدهد، چون شاخه else آن را رئیس مینماید که می تواند سبب به بروز باگ گردد. با این هم اکنون، در صورتیکه که کامپایلر در طی اضافه کردن یک زیرکلاس تازه خطایی ساخت و ساز نماید، عالی خواهد بود.
برای حل این زمینه، می توانید از کلاسهای sealed به کارگیری فرمایید. چنان که اشاره کردیم، کلاس sealed قابلیت و امکان ساخت و ساز زیرکلاس را محصور میسازد. همینطور هنگامی که تمامی زیرکلاسهای یک کلاس sealed به طور یک عبارت when باشند، لزومی به به کارگیری از شاخه else نخواهد بود.
برای ساختوساز یک کلاس sealed، بایستی از مادیفایر sealed مانند نمونه پایین به کارگیری فرمایید:
sealed class Expr

راهکارهای کاهش CPC در کمپینها